import sublime
import sublime_plugin
import os
import copy
from .mywork import ConstHelper

def get_max_width(*args):
    max_width = 0
    for arg in args:
        if len(str(arg)) > max_width:
            max_width = len(str(arg))
    return max_width

def formInsertString(defDatas, maxDatas, minDatas):
    insertStr = '''
#define funCodeMax(x)       gci8u_funCode[x * 3 + 2]
#define FAC_SET[x]          gci8u_funCode[x * 3 + 1]
#define funCodeMin(x)       gci8u_funCode[x * 3 + 0]
INT8U const gci8u_funCode[] =
{
'''
    for i in range(0, len(defDatas)):
        insertStr += '    {' + minDatas[i] + ', ' + \
            defDatas[i] + ', ' + maxDatas[i] + '},\n'
    insertStr += '};\n'
    return insertStr

def getConstDatas(view):
    defDatas = ConstHelper.getDatas(view, ConstHelper.defConstPattern)
    minDatas = ConstHelper.getDatas(view, ConstHelper.minConstPattern)
    maxDatas = ConstHelper.getDatas(view, ConstHelper.maxConstPattern)
    if not defDatas or not minDatas or not maxDatas:
        return
    return [defDatas, maxDatas, minDatas]

def convertConstDatas(view):
    datas = getConstDatas(view)
    insertStr = formInsertString(datas[0], datas[1], datas[2])

    return insertStr

def convert_from_datas(datas):
    head = ['INT8U const FAC_SET[]      = {',
        'INT8U const FUN_CODE_MAX[] = {',
        'INT8U const FUN_CODE_MIN[] = {']

    defDatas = head[0]
    maxDatas = head[1]
    minDatas = head[2]
    for i in range(0, len(datas[0])):
        max_width = get_max_width(datas[0][i], datas[1][i], datas[2][i])
        if i < len(datas[0]) - 1:
            defDatas = defDatas + ' ' * (max_width - len(str(datas[0][i]))) + datas[0][i] + ', '
            maxDatas = maxDatas + ' ' * (max_width - len(str(datas[1][i]))) + datas[1][i] + ', '
            minDatas = minDatas + ' ' * (max_width - len(str(datas[2][i]))) + datas[2][i] + ', '
        else:
            defDatas = defDatas + datas[0][i] + '};\n'
            maxDatas = maxDatas + datas[1][i] + '};\n'
            minDatas = minDatas + datas[2][i] + '};\n'

    return [defDatas, maxDatas, minDatas]

def get_const_region(view):
    defRegion = ConstHelper.getConstRegion(view, ConstHelper.defConstPattern)
    maxRegion = ConstHelper.getConstRegion(view, ConstHelper.maxConstPattern)
    minRegion = ConstHelper.getConstRegion(view, ConstHelper.minConstPattern)
    region = defRegion.cover(maxRegion).cover(minRegion)

    return view.full_line(region)

def check_file_name(view):
    file_name = os.path.basename(view.file_name())
    if file_name == 'test.C':
        return True
    else:
        return False

class FormatConstCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        const_region = get_const_region(self.view)
        const_datas = convert_from_datas(getConstDatas(self.view))
        formatString = const_datas[0] + const_datas[1] + const_datas[2]
        self.view.replace(edit, const_region, formatString)

class FormatConstByDatasCommand(sublime_plugin.TextCommand):
    def run(self, edit, datas):
        if not datas:
            return
        const_region = get_const_region(self.view)
        const_datas = convert_from_datas(datas)
        formatString = const_datas[0] + const_datas[1] + const_datas[2]
        self.view.replace(edit, const_region, formatString)

class InsertConstCommand(sublime_plugin.TextCommand):
    origin_datas = []

    def apply_change(self, arg):
        args = arg.split(',')
        datas = copy.deepcopy(self.origin_datas)
        index = 0
        for i, s in enumerate(args):
            if i == 0:
                index = int(s.strip())
                for data in datas:
                    data.insert(index, '0')
            elif i < 4:
                datas[i - 1][index] = s.strip()

        print(args)
        print(datas)
        self.view.run_command('format_const_by_datas', {'datas': datas})

    def on_done(self, arg):
        self.apply_change(arg)
        return

    def on_change(self, arg):
        self.apply_change(arg)
        return

    def on_cancel(self):
        self.view.run_command('format_const_by_datas', {'datas': self.origin_datas})
        return

    def run(self, edit):
        self.origin_datas = getConstDatas(self.view)
        if not self.origin_datas:
            return

        self.view.window().show_input_panel(
            'insert const:',
            '',
            self.on_done,
            self.on_change,
            self.on_cancel
        )

class HilightConst(sublime_plugin.EventListener):
    phantom_sets = {}
    phantoms = []

    def check_scope(self, view):
        scope_name = view.scope_name(1)
        return scope_name.find('source.C')

    def create_phantom(self, view):
        const_datas = getConstDatas(view)
        if not const_datas:
            return
        min_region = ConstHelper.getConstRegion(view, ConstHelper.minConstPattern)
        m_region = sublime.Region(min_region.begin() + 4, min_region.end())

        content = '''
            <body>
                <style type="text/css">
                    div.content {
                        background-color: #32AFF4;
                        border-radius: 4px;
                        color: #FFFFFF;
                        padding-left: 2px;
                        padding-right: 2px;
                    }
                </style>
                <div class="content">
            '''

        for i, data in enumerate(const_datas[0]):
            data_width = get_max_width(const_datas[0][i], const_datas[1][i], const_datas[2][i])
            space_str = '&nbsp;' * (data_width - len(str(i)) + 2)
            content = content + space_str + str(i)

        content = content + '''
                    </div>
                </body>
            '''
        
        phantom = sublime.Phantom(
            m_region,
            content,
            sublime.LAYOUT_BELOW)
        self.phantoms.append(phantom)

    def update_phantom_set(self, view):
        buffer_id = view.buffer_id()
        if buffer_id in self.phantom_sets:
            phantom_set = self.phantom_sets[buffer_id]
        else:
            phantom_set = sublime.PhantomSet(view, "HighlighConst")
            self.phantom_sets[buffer_id] = phantom_set

        phantom_set.update(self.phantoms)

    def update_view(self, view):
        view.erase_phantoms('HilightConst')

        if not self.check_scope(view):
            return

        self.phantoms = []
        self.create_phantom(view)
        self.update_phantom_set(view)

    def on_post_save(self, view):
        self.update_view(view)

    def on_activated(self, view):
        self.update_view(view)
